package property;

import com.gitee.feizns.dynamic.bean.Property;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * <b>Property测试类</b>
 * @author feizns
 * @since 2019/6/15 0015
 */
public class PropertyDemo {

    public static void main(String[] args) {

        User userA = new User("A");
        User userB = new User("B");
        User userC = new User("C");
        userA.setUser(userB);
        userB.setUser(userC);

        System.out.println(Property.of(userA, User::getUser).get(User::getDesc).val()); //B

        Property<User, User> userAPro = Property.of(userA, User::getUser);

        System.out.println(userAPro.val());                  //PropertyDemo.User(desc=B, user=null)
        System.out.println(userAPro.isWritable());           //是否可写
        System.out.println(userAPro.isReadable());           //是否可读

        System.out.println(userAPro.getSource() == userA);   //true

        //public property.PropertyDemo$User property.PropertyDemo$User.setUser(property.PropertyDemo$User)
        System.out.println(userAPro.writeMethod());

        //public property.PropertyDemo$User property.PropertyDemo$User.getUser()
        System.out.println(userAPro.readMethod());

        Object user = userAPro.get("user").val();
        System.out.println(user == userC);          //true

        System.out.println(userAPro.get("user")
                .get("xxx").val());                 //null：（就算没有的属性也不会有异常）

        Admin admin = userAPro.val(Admin.class);
        System.out.println(admin);                  //PropertyDemo.Admin(desc=B)

        System.out.println(userAPro.val(Admin.class) == admin);   //false

        Property<Integer, Admin> property = Property.of(admin, "id");
        System.out.println(property.isAnnotationPresent(Ano.class));  //true

        System.out.println(Property.of(admin, "tmp").isAnnotationPresent(Ano.class)); //true

    }

    @Data
    @Accessors(chain = true)
    public static class User {

        private String desc;

        private User user;

        public User(String desc) {
            this.desc = desc;
        }

    }

    @Accessors(chain = true)
    public static class Admin {

        @Getter
        @Setter
        private String desc;

        private Integer id;

        @Ano
        private String tmp;

        @Ano
        public void setId(Integer id) {
            this.id = id;
        }

        public static Admin valueOf(User user) {
            return new Admin().setDesc(user.getDesc());
        }

    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD, ElementType.METHOD})
    public @interface Ano {

    }

}
